์ž‘์„ฑ: 2026-03-04 04:03:38์ˆ˜์ •: 2026-03-04 04:03:38

Spring Boot ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ (Global Exception Handling)

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ํ•œ ๊ณณ์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ์ผ๊ด€๋œ ์—๋Ÿฌ ์‘๋‹ต์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํ”„๋ง ๋ถ€ํŠธ์—์„œ ๊ฐ€์žฅ ๊ถŒ์žฅ๋˜๋Š” @RestControllerAdvice ํ™œ์šฉ๋ฒ•์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.


1. ๊ฐœ์š”: ๊ฐœ๋ณ„ ์ฒ˜๋ฆฌ๊ฐ€ ์•„๋‹Œ ์ „์—ญ ์ฒ˜๋ฆฌ์˜ ํ•„์š”์„ฑ

๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์†Œ๋“œ๋งˆ๋‹ค try-catch๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์Šคํ”„๋ง์€ AOP(๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ) ๊ธฐ์ˆ ์„ ํ™œ์šฉํ•œ ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.


2. ๊ตฌํ˜„ ๋‹จ๊ณ„

โ‘  ๊ณตํ†ต ์—๋Ÿฌ ์‘๋‹ต ๊ฐ์ฒด (Error Response)

ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•  ์ผ์ •ํ•œ ํ˜•์‹์˜ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

@Getter
@Builder
public class ErrorResponse {
    private String code;
    private String message;
    private int status;
}

โ‘ก ์‚ฌ์šฉ์ž ์ •์˜ ์˜ˆ์™ธ (Custom Exception)

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋งž์ถฐ ๋‹ค์–‘ํ•œ ์˜ˆ์™ธ๋ฅผ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ปค์Šคํ…€ ์˜ˆ์™ธ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

โ‘ข ์ „์—ญ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ธฐ (@RestControllerAdvice)

๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ๊ฐ€๋กœ์ฑ„์–ด ์ฒ˜๋ฆฌํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

@RestControllerAdvice
public class GlobalExceptionHandler {
 
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleUserNotFound(UserNotFoundException ex) {
        ErrorResponse response = ErrorResponse.builder()
                .code("USER_NOT_FOUND")
                .message(ex.getMessage())
                .status(HttpStatus.NOT_FOUND.value())
                .build();
        return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
    }
 
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
        ErrorResponse response = ErrorResponse.builder()
                .code("INTERNAL_SERVER_ERROR")
                .message("์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.")
                .status(HttpStatus.INTERNAL_SERVER_ERROR.value())
                .build();
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

3. ํ•ต์‹ฌ ์žฅ์ 

  1. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋‹จ์ˆœํ™”: ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์™„์ „ํžˆ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ผ๊ด€๋œ ์—๋Ÿฌ ๊ทœ๊ฒฉ: ๋ชจ๋“  API๊ฐ€ ๋™์ผํ•œ JSON ์—๋Ÿฌ ํ˜•์‹์„ ์‘๋‹ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  3. ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ: ์ƒˆ๋กœ์šด ์˜ˆ์™ธ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด๋„ GlobalExceptionHandler ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

4. ์š”์•ฝ

  • @RestControllerAdvice๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ์˜ ์˜ˆ์™ธ๋ฅผ ์ค‘์•™ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
  • @ExceptionHandler๋ฅผ ํ†ตํ•ด ํŠน์ • ์˜ˆ์™ธ ํƒ€์ž…๋ณ„๋กœ ์‘๋‹ต์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ํ‘œ์ค€ ์—๋Ÿฌ ์‘๋‹ต ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๊ฒฌ๊ณ ํ•œ ๋ฐฑ์—”๋“œ ์‹œ์Šคํ…œ ๊ตฌ์ถ•์˜ ์‹œ์ž‘์ž…๋‹ˆ๋‹ค.